package basic_grammar

import (
	"encoding/json"
	"fmt"
)

// 结构体

func TestStruct() {
	//firstMeetStruct()
	//createStruct()
	//testValueType()
	testInherited()
	//testTag()
}

/*
type 结构体名 struct {
	fileName fileType
	...
}
结构体可以绑定方法
*/
func firstMeetStruct() {
	uzi := Player{"uzi", "英雄联盟"}
	uzi.PlayGame()
	uzi.GameName = "斗地主"
	uzi.PlayGame()
	sky := Player{"sky", "魔兽争霸"}
	sky.PlayGame()
}

type Player struct {
	Name     string
	GameName string
}

func (p Player) PlayGame() {
	fmt.Printf("%s正在玩%s\n", p.Name, p.GameName)
}

// 创建结构体
func createStruct() {
	// 1. 声明结构体
	var player1 Player
	player1.Name = "TH000"
	player1.GameName = "魔兽争霸"
	fmt.Println(player1)

	// 2. 声明时初始化
	player2 := Player{GameName: "CS"}
	fmt.Println(player2)

	// 3. 使用new关键字
	player3 := new(Player)
	fmt.Printf("%v,%T\n", player2, player2)
	player3.Name = "letme"
	(*player3).GameName = "魔兽争霸"
	fmt.Println(player3)
	fmt.Println(*player3)

	// 4. 使用&,实际上3和4都是指针,但使用时底层已经优化了
	player4 := &Player{}
	fmt.Println(player4)

}

// 值类型

func testValueType() {
	g := Game{"只狼", "ARPG"}
	fmt.Println(g.GetName())
	g.SetName("紫塞秋风")
	fmt.Println(g.GetName())
}

type Game struct {
	name     string
	typeName string
}

func (g Game) GetName() string {
	return g.name
}

func (g *Game) SetName(name string) {
	g.name = name
}

func (g Game) GetTypeName() string {
	return g.typeName
}

func (g *Game) SetTypeName(typeName string) {
	g.typeName = typeName
}

//golang中可以自定义类型
//编译器会认为是两种类型,因此无法直接赋值,如果真的要赋值,可以强制类型转换
//方法是绑定在指定数据类型上的函数

type Integer int

func (i Integer) isEven() bool {
	return i%2 == 0
}

func testIntegerEven() {
	var a Integer
	b := 11
	a = Integer(b)
	if a.isEven() {
		fmt.Println("我是偶数")
	} else {
		fmt.Println("我是奇数")
	}
}

// 结构体如果要互相转换,需要字段完全一样(名称,数量,类型)

// 实现继承
// 利用匿名结构体实现
// 匿名结构体可以省略,如果本身找不到相应属性和方法,则会从匿名结构体中找
// 编译器会就近查找,如果有重复的属性方法,则必须使用匿名结构体
// 同名,同参数,同返回值的方法,可以绑定不同的结构体,类似实现重载的效果,但不是传统意义的重载(继承也不是传统的继承)
type LoLPlayer struct {
	Player
	hero map[string]string
}

func (p LoLPlayer) PractiseHero() {
	p.PlayGame()
	fmt.Printf("%s正在练%s,放技能%s\n", p.Name, p.hero["name"], p.hero["skill"])
}

func testInherited() {
	hero := map[string]string{
		"name":  "亚索",
		"skill": "斩钢闪"}
	lolPlayer := LoLPlayer{Player{"uzi", "英雄联盟"}, hero}
	lolPlayer.PractiseHero()
}

// 字段 可以加一个tag
type User struct {
	Username string `json:"user_name"`
	Pwd      string `json:"pwd"`
}

func testTag() {
	user := User{"heheyixiao", "1qaz@WSX"}
	jsonStr, err := json.Marshal(user)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(string(jsonStr))
}

/*
go test –coverprofile=c.out
go tool cover –html=c.out
*/
